package reporting;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.*;
import static util.ConstantCollection.*;

import util.*;

class HtmlReport extends TemplateReport{
	private FileWork fw = FileWork.getInstance();
	private TestConfiguration tc = TestConfiguration.getInstance();
	private Util u = new Util();
	
	private String i_logRightFilename = "right.htm";
	private String i_logLeftFilename = "left.htm";
	private String i_logMainFilename = "log.htm";
	private String i_logRightIterator;
	private Integer i_logIterator = 0;
	
	public HtmlReport(String name) {
		super(name);
		String tempPath;
		tempPath = tc.getEnv("_logpath") + "html/";
		
	    if(!fw.existsFileOrDir(tempPath)){
			fw.createDir(tempPath);
		}
		tempPath = tempPath + getName();  
	    if(!fw.existsFileOrDir(tempPath)){
			fw.createDir(tempPath);
		}
	}
	
	public void report(Message objMsg){
		reportEventWText_HTML(objMsg.getId(), objMsg.getStatus(), objMsg.getHeader(), objMsg.getDescription());
	}

	/**
	 * Saves status and statistics information about current test into the "testStatus.txt" and "summary.htm" files. 
	 */
	private void save(){
		    //TODO replace real data
		    String testName = "Test Name"; //should be environment variable
		    String testStatus = "Pass";
		    Integer errorCnt = 1;
		    Integer warningCnt = 1;
		    Integer cpFailedCnt = 1;
		    Integer stepCnt =1;
		    Integer stepPassedCnt = 1;
		    Integer stepWarningCnt = 1;
		    Integer stepFailedCnt = 1;
		    Integer cpCnt = 1;
		    Integer cpPassedCnt = 1;
		    //
		    		   
			String txt;
			String logFilename;
			
			
			txt = "<HTML><BODY>";
			txt = txt.concat("<H2>Test ").concat(testName).concat(" Summary</H2>");
			txt = txt.concat("<B>Overall Test Status:</B>").concat(testStatus).concat("<br/>");
			txt = txt.concat("<hr/><p><h3>Problems Summary:</h3><br/>");
			txt = txt.concat("<B>Errors reported: </B>").concat(errorCnt.toString()).concat("<br/>");
			txt = txt.concat("<B>Warnings reported: </B>").concat(warningCnt.toString()).concat("<br/>");
			txt = txt.concat("<B>Checkpoints failed: </B>").concat(cpFailedCnt.toString()).concat("<br/>");
			txt = txt.concat("</p>");
		
			txt = txt.concat("<hr/><p><h3>Steps Summary: </h3><br/>");
			txt = txt.concat("<B>Steps Total: </B>").concat(stepCnt.toString()).concat("<br/>");
			txt = txt.concat("<B>Steps Passed: </B>").concat(stepPassedCnt.toString()).concat("<br/>");
			txt = txt.concat("<B>Steps with Warnings: </B>").concat(stepWarningCnt.toString()).concat("<br/>");
			txt = txt.concat("<B>Steps Failed: </B>").concat(stepFailedCnt.toString()).concat("<br/>");
			txt = txt.concat("</p>");
		
			txt = txt.concat("<hr/><p><h3>Checkpoints Summary:</h3><br/>");
			txt = txt.concat("<B>Checkpoints Total: </B>").concat(cpCnt.toString()).concat("<br/>");
			txt = txt.concat("<B>Checkpoints Passed: </B>").concat(cpPassedCnt.toString()).concat("<br/>");
			txt = txt.concat("<B>Checkpoints Failed: </B>").concat(cpFailedCnt.toString()).concat("<br/>");
			txt = txt.concat("</p>");
		
			txt = txt.concat("</HTML></BODY>");
			
			//needs correct path
			logFilename = "d:/Summary.htm";
			FileWork fs = new FileWork();
			fs.writeFile(logFilename, txt);
			
			
	}
	
	/**
	 * Gets index for current event to report it to HTML log (event index is not displayed in log, but it is used internally for link references).
	 * and increases event iterator by 1.
	 * @return string, containing value of the current event index.
	 */
	private String getLogIterator(){
		String result;
		result = i_logIterator.toString();
		i_logIterator = i_logIterator + 1;
		return result;
	}
	
	/** Actually gets path (not name!) to HTML log file, containing detailed event descriptions.
	 * @return string, containing full path to the HTML log file with detailed event descriptions.
	 */
	private String getLogDetailsFileName(){
		return fileGenerateResPath(i_logRightFilename);
	}
	
	/** Actually gets path (not name!) to HTML log file with event contents.
	 * @return string, containing full path to the HTML log file with event contents.
	 */
	private String getLogContentsFileName(){
		return fileGenerateResPath(i_logLeftFilename);
	}

	/** Actually gets path (not name!) to the main HTML log file.
	 * @return string, containing full path to the main HTML log file.
	 */
	private String getLogMainFileName(){
		return fileGenerateResPath(i_logLeftFilename);
	}
	

	/**
	 * Starts new log file when current log file size exceeds limit (<see cref="LOG_SWAP_SIZE"/> constant) and adds reference to the new log file. 
	 */
	private void swapLogFile(){
		    System.out.println("DONE\tSwapping log file '" + i_logRightFilename + "'");
			i_logRightIterator = i_logRightIterator + 1;
			i_logRightFilename = "right" + i_logRightIterator.toString() + ".htm";
			//ReportEventHTML_SE  micDone, "Log file will be swapped.", "Log is continued in file: <A href='" & i_logRightFilename & "'>" & i_logRightFilename & "</A>"
			//ReportEventHTML_SE  micDone, "Log file swapped", "Log is continued from file: <A href='right" & CStr(i_logRightIterator - 1) & ".htm'>right" & CStr(i_logRightIterator - 1) & ".htm</A>"
	}
	
	
	/**
	 * Creates HTML log file with all headers.
	 */
	private void createReportHTML(){
			i_logRightIterator = "0";
			String text;
			text = "<HTML><head><title>" + u.encodeHTML(tc.getEnv("_testtitle")) + " - Test Report</title><META http-equiv=Content-Type content='text/HTML; charset=windows-1251'></head>\n"; 
			text = text + "<frameset   frameborder='0'> <frameset  cols='30%, 70%' frameborder='0' bordercolor='#ffffff'>\n";
			text = text + "<frame src='" + i_logLeftFilename + "'  name='LeftFrame' scrolling='yes' frameborder='1'>";
			text = text + "<frame src='" + i_logRightFilename + "' name='RightFrame'></frameset></frameset><noframes> <BODY bgcolor='#f5f5f5'> <p>Need Frames</p>\n"; 
			text = text + "</BODY></noframes></HTML>";
			fw.writeFile(fileGenerateResPath(i_logMainFilename), text);
	}
	
    /**
     * @param status
     * @return
     */
    public String getStatusColor(int status){
    	String statusColor;
        switch(status){
			case 0: statusColor = "blue"; break;
			case 1: statusColor = "gray"; break;
			case 2: statusColor = "black"; break;
        	case 3: statusColor = "green"; break;
        	case 4: statusColor = "magenta"; break;
        	case 5: statusColor = "FF7AFF"; break; //pink
        	case 6: statusColor = "red"; break;
        	case 7: statusColor = "8700FF"; break; //purple
        	default: statusColor = "red"; break;
        }

        return statusColor;
    }
    
    private String fileGenerateResPath(String fileName){
    	return tc.getEnv("_logpath") + "html/" + getName() + "/" + fileName;
    }
  

    /**Gets the full content of the "left.htm" HTML log file and processed it by <see cref="htmlTextGetBody"/> function.
     * @return String, contains BODY of the "left.htm" HTML log file.
     */
    private String getContentsHtml(){
    	String text;
    		if(fw.existsFileOrDir(getLogContentsFileName())){
    			//Load log file
    			text = fw.readFile(getLogContentsFileName());
    			text = htmlTextGetBody(text);
    		}
    		else{
    			//Init log file
    			createReportHTML();
    			text = "<STYLE TYPE='text/css'>"; 
    			text = text.concat("<STYLE TYPE='text/css'>");
    			text = text.concat(".{"); 
    			text = text.concat("  font-family:arial;"); 
    			text = text.concat("  text-decoration:none"); 
    			text = text.concat("}"); 
    			text = text.concat("a{"); 
    			text = text.concat("  font-family:arial;"); 
    			text = text.concat("  font-size: 10pt;"); 
    			text = text.concat("  color:black;"); 
    			text = text.concat("  text-decoration:none"); 
    			text = text.concat("}"); 
    			text = text.concat("a:visited{"); 
    			text = text.concat("  font-family:arial;"); 
    			text = text.concat("  font-size: 10pt;"); 
    			text = text.concat("  color:black;"); 
    			text = text.concat("  text-decoration:none"); 
    			text = text.concat("}"); 
    			text = text.concat("</STYLE>"); 
    			text = text.concat("<B><a href='summary.htm' class='text' target='RightFrame' style='color:D8A170;font-size:16pt'><u><NOBR>Test Summary</NOBR></u></a></B><BR><BR>\n"); 
    			
    			text = text.concat("<B><a href='" + i_logRightFilename + "#0' class='text' target='RightFrame'><NOBR>Test Log Started</NOBR></a></B><BR><BR>\n");
    		}
    		return text;
    }


    /**Gets the full content of the "log.htm" HTML log file and processed it by <see cref="htmlTextGetBody"/> function.
     * @return String, contains BODY of the "log.htm" HTML log file.
     */
    private String getLogHtml(){
    	String text;
    	
    	if(fw.existsFileOrDir(getLogDetailsFileName())){
    		//Load log file
    		text = fw.readFile(getLogDetailsFileName());
    		text = htmlTextGetBody(text);
    	}
    	else{
    		//Init log file
			text = "<a name='#" + getLogIterator() + "' target='RightFrame'/>";
    		text = text.concat("<table align='center' style='border:0px;background:#FFFFFF'>");
    		text = text.concat("  <tr style='border:0px'>");
    		text = text.concat("    <td style='border:0px' align='left' width='200'><b style='font-size:13pt'>Test title:</b></b>");
    		text = text.concat("    <td style='border:0px' valign='center' width='300'><b style='font-size:25pt;color:808080'>" + tc.getEnv("_testtitle") + "</b></td>");
    		text = text.concat("	  </tr>");
    		text = text.concat("  <tr style='border:0px' style='border:0px'>");
    		text = text.concat("    <td style='border:0px' align='left'><b style='font-size:13pt'>Test name:</b></td>");
    		text = text.concat("	    <td style='border:0px' valign='center'><b style='font-size:17pt'>" + tc.getEnv("_testname") + "</b></td>");
    		
    		text = text.concat("	  </tr>");
    		text = text.concat("	  <tr style='border:0px' style='border:0px'>");
    		text = text.concat("	    <td style='border:0px' align='left'><b style='font-size:13pt'>Time zone:</b></td>");
    		text = text.concat("	    <td style='border:0px' valign='center'><b style='font-size:14pt'>" + u.getTimeZone() + "</b></td>");
    		text = text.concat("	  </tr>");
    		text = text.concat("	  <tr style='border:0px'>");
    		text = text.concat("        <td style='border:0px' align='left'><b style='font-size:13pt'>Run started:</b></td>");
    		text = text.concat("   <td style='border:0px' valign='center'><b style='font-size:14pt'>" + u.getDateTimeNow() + "</b></td>");
    		text = text.concat("  </tr>");
    		text = text.concat("</Table><br><br><hr><br>");
    	}	
    		return text;
    	
    }

    /** Converts specified <i>eventStatus</i> into appropriate HTML string.
     * @param eventStatus Status message
     * @return HTML formatted string, contains information about status.
     */
    private String getStatusHTML(Integer eventStatus){
    	return "<FONT style='color:" + getStatusColor(eventStatus) + "'>" + getStatusName(eventStatus) + "</FONT>";
    }
    
    /** Remove all BODY and HTML tags from <htmlString> source text, <htmlString> is assumed to be framework-generated HTML file's text
     * @param htmlString Input html
     * @return <htmlString> cleaned from <BODY>, </BODY>, <HTML>, </HTML> substrings
     */
    private String htmlTextGetBody(String htmlString){
    	String result = null;
    	if (htmlString == null){
    		result = ""; 
    	}
    	else{
    		try{
    	   		String t;
    	   		t = htmlString;
    	   		t = t.replace("<HTML>", "");
    	   		t = t.replace("<HTML>", "");
    	   		t = t.replace("</HTML>", "");
    	   		t = t.replace("<BODY>", "");
    	   		t = t.replace("</BODY>", "");
    	   		t = t.replace("<html>", "");
    	   		t = t.replace("</html>", "");
    	   		t = t.replace("<body>", "");
    	   		t = t.replace("</body>", "");
    	   		result = t;
    		}
    		catch(Exception e){
    			System.err.println("HtmlTextGetBody :: " + e.getMessage());
    		}
    	}
    	return result;
    }
    
    /**Adds specified text to the end of file with given <i>filePath</i>.
     * @param textToAppend Specifies text, which should be added to file.
     * @param filePath Specifies full path to the file, including filename and extension. 
     * @return Result of appending - True, if specified text has been added to the file. False if any error occurs while saving a file.
     */
    private Boolean appendToHtml(String textToAppend, String filePath){
    
    		String resText;
    	    resText = fw.readFile(filePath);
    		resText = htmlTextGetBody(resText);
    		resText = resText + "\n" + textToAppend;
    		resText = "<HTML><BODY>\n"  + resText + "\n</BODY></HTML>";
    		return fw.writeFile(filePath, resText);
    }
    
    /**Reports an event about log file swapping to the HTML log.
     * @param eventStatus Specifies event status. Can be one of the status constants: micDone, micPass, micWarning, micFail. (For more information about status constants see QTP help)
     * @param eventHeader Specifies event header.
     * @param eventDesc Specifies detailed information about event.
     */
    private void reportEventHTML_SE(Integer eventStatus, String eventHeader, String eventDesc){

    		String logMainText;
    		logMainText = getLogHtml();
    		
    		logMainText = logMainText + "<HR>\n"; 
    		logMainText = logMainText + "<B>Log Event: </B>" + eventHeader + "<BR>\n";
    		logMainText = logMainText + eventDesc + "<BR>\n";
    		logMainText = logMainText + "<B>Status: </B>" + getStatusHTML(eventStatus); 
    		logMainText = "\n<HTML><BODY>" + logMainText + "</BODY></HTML>";
    		
    		fw.writeFile(getLogDetailsFileName(), logMainText);
    }
    
    private void reportEventWText_HTML(String eventId, Integer eventStatus, String eventHeader, String eventDesc){
    	String mainText = "";
		String logMainText;
		logMainText = getLogHtml();
		String eventIndex;
		eventIndex = getLogIterator();
			
		logMainText = "<HTML><BODY>" + logMainText + (mainText + "</BODY></HTML>");
		fw.writeFile(getLogDetailsFileName(), logMainText);
	
		String logContentsText;
		logContentsText = getContentsHtml();
		String contents = "";
		contents = contents + "" + "<a href='" + i_logRightFilename + "#" + eventIndex + "' class='text' target='RightFrame'>";
		if(eventId == null){
			contents = contents + "<NOBR><b style='padding-left:2px;font-family:arial black;font-size:12; color:919191'>" + u.encodeHTML(eventHeader) + "</b></a></NOBR>" + "<BR><FONT size=-5 style='color:#FFFFFF'>_</FONT>";
		}else{
			contents = contents + "<NOBR><b style='padding-left:10px'>" + getStatusHTML(eventStatus) + " " + eventId + "</b> " + ": <b>" + u.encodeHTML(eventHeader) + "</b></a></NOBR>" + "<BR><FONT size=-5 style='color:#FFFFFF'>_</FONT>";
		}
		logContentsText = "<HTML><BODY>" + logContentsText + (contents + "</BODY></HTML>");
		fw.writeFile(getLogContentsFileName(), logContentsText);
		
		byte[] utf8 = null;
		int byteCount = 0;
		try {
		  utf8 = logMainText.getBytes("UTF-8");
		  byteCount = utf8.length;
		} catch (UnsupportedEncodingException ex) {
		  ex.printStackTrace();
		}

		if( byteCount > LOG_SWAP_SIZE){
			swapLogFile();
		}
    }

    
    
    
    
    
    
    
    
    private void createLeftFrame(String eventId, int eventStatus) {
    	String logContentsText;
		logContentsText = getContentsHtml();
		String contents = "";
		contents = contents + " " + "<a href='" + i_logRightFilename + "#" + getLogIterator() + "' class='text' target='RightFrame'>";
		if(eventId == null){
			contents = contents + "<NOBR><b style='padding-left:2px;font-family:arial black;font-size:12; color:919191'>" + tc.getEnv("_testtitle") + "</b></a></NOBR>" + "<BR><FONT size=-5 style='color:#FFFFFF'>_</FONT>";
		}else{
			contents = contents + "<NOBR><b style='padding-left:10px'>" + getStatusHTML(eventStatus) + " " + eventId + "</b> " + ": <b>" + tc.getEnv("_testname") + "</b></a></NOBR>" + "<BR><FONT size=-5 style='color:#FFFFFF'>_</FONT>";
		}
		logContentsText = "<HTML><BODY>" + logContentsText + (contents + "</BODY></HTML>");
		fw.appendFile(getLogContentsFileName(), logContentsText);
    }
    
    private String createHtmlStyle() {
		String eventIndex;
		eventIndex = getLogIterator();
    	String mainText;
        mainText = "<style>\n";
        mainText = mainText + ("  TABLE {");
        mainText = mainText + ("    border: 4px double black;\n");
        mainText = mainText + ("    border-collapse: collapse;\n");
        mainText = mainText + ("    font-family:Arial;\n");
        mainText = mainText + ("    background:#CCCCCC\n");
        mainText = mainText + ("  }");
        mainText = mainText + ("  TH {\n");
        mainText = mainText + ("    text-align: center;\n");
        mainText = mainText + ("    padding: 5px;\n");
        mainText = mainText + ("    border: 1px solid black\n");
        mainText = mainText + ("  }\n");
        mainText = mainText + ("  TD {\n");
        mainText = mainText + ("    padding: 5px;\n");
        mainText = mainText + ("    border: 1px solid black\n");
        mainText = mainText + ("  }\n");
        mainText = mainText + (".head{color:#000000;font-size:11pt;font-weight:bold}\n");
        mainText = mainText + (".name{color:#000000;font-size:10pt;font-family:Arial;font-weight:bold}\n");
        mainText = mainText + (".create{color:#0066CC;font-size:11pt;font-weight:bold}\n");
        mainText = mainText + (".rez{font-size:11pt;font-weight:bold}\n");
        mainText = mainText + (".steep{background: #FFFFFF;border: 0px solid black;font-size:9pt}\n");
        mainText = mainText + (".resoult{font-size:9pt;background: #FFFFFF;border: 0px solid black;border-left: 1px solid black;border-right: 1px solid black;font-weight:bold}\n");
        mainText = mainText + (".coments{background:#FFFFFF;color:#000000;font-size:10pt;font-family:Arial;font-weight:bold;font-style:italic}\n");
        mainText = mainText + (".cloc{color:#000000;font-size:9pt;background:#FFFFFF}\n");
        mainText = mainText + (".nom{font-size:14pt;font-family:Courier;font-weight:lighter;background:#b7b7b7}\n");
        mainText = mainText + ("</style>\n\n");
        
        return mainText;
    }
    
    private String createHead(int eventStatus, int sumStep, String eventId) {
    	String mainText;
    	sumStep+=1;
        mainText = "<a name='" + eventId + "' target='RightFrame'/>\n";
    	mainText = mainText + ("            <table bgcolor='CCCCCC' align='center'>\n");
        mainText = mainText + ("  <tr class='head' valign='middle' bgcolor='" + getStatusColor(eventStatus) + "'>\n");
        mainText = mainText + ("    <th align='center' width='50'>ID</th>\n");
        mainText = mainText + ("    <th align='center' colspan='2' width='500'>DETAILS</th>\n");
        mainText = mainText + ("    <th align='center' width='50'>STATUS</th>\n");
        mainText = mainText + ("    <th align='center' width='50'>TIME</th>\n");
        mainText = mainText + ("  </tr>\n");
        mainText = mainText + ("  <tr valign='middle'>\n");
        mainText = mainText + ("    <td class='nom' align='center' rowspan='" + sumStep + "'>" + eventId + ".</td>\n");
        mainText = mainText + ("    <td class='name' width='105'>Name</td>");
        mainText = mainText + ("    <td class='create' width='395'>" + tc.getEnv("_testname") + "</td>\n");
        mainText = mainText + ("    <td class='rez' align='center'>" + getStatusHTML(eventStatus) + "</td>\n");
        mainText = mainText + ("    <td class='cloc' align='center' rowspan='" + sumStep + "'>" + u.getTimeNow() + "</td>\n");
        mainText = mainText + ("  </tr>\n");     

        return mainText;
    }
    
	public void reportStep(TCStep step) {
		String text;
		final String ACTION_TITLE = "Input/Action";
		final String EXPECTED_TITLE = "Expected Result";
		
		//Generate Details text
		String detail = "";
    	String lastTypeItem = "action";
    	    	
    	int sumStep = 0;
    	int sumRow = 0;
		String inputAction = "";
		String actionStep = "";
		String tempPath = tc.getEnv("_logpath") + "html/main/";
		
    	for (Iterator<StepItem> it = step.getItemCollection().iterator(); it.hasNext(); sumRow++) {
    		StepItem item = it.next();
    		sumStep = 0;
    		actionStep = "";
     		inputAction = "";
    		if (item.getType() == "action") {
           	 	if (lastTypeItem == "cp") {
           	 		lastTypeItem = "action";
           	 	}
       	 		sumStep++;
       	 		inputAction = ("<tr valign='middle'>");
       	 		inputAction = inputAction + ("<td class='name' rowspan='" + sumStep + "'>" + ACTION_TITLE + "</td>\n"); 
       	 		actionStep = actionStep + ("<td class='steep'>" + item.getStepNum() + ". " + item.getDescription() + ".</td>\n");
       	 		actionStep = actionStep + ("<td class='resoult' align='center' style='color: " + getStatusColor(item.getStatus()) + "'>" + getStatusName(item.getStatus()) + "</td>" + "</tr>\n");
    		} else if (item.getType() == "cp") {
    			if (lastTypeItem == "" || lastTypeItem == "action") {
    				lastTypeItem = "cp";
    				detail = detail + ("<tr valign='middle'>\n");
    				detail = detail + ("  <td class='name'>" + EXPECTED_TITLE + "</td>\n");
    				detail = detail + ("  <td class='coments'>" + item.getDescription() + "</td>\n");
    				detail = detail + ("  <td class='resoult' align='center' style='color: " + getStatusColor(item.getStatus()) + "; border: 1px solid black'>" + getStatusName(item.getStatus()) + "</td>\n");
               	 	detail = detail + ("</tr>\n");
    			}
    		}	
       	 		detail = detail + inputAction + actionStep + "\n";           	 	
    	}

    	text = "<html><body>" + getLogHtml() +createHtmlStyle() + createHead(step.getStatus(), sumRow, step.getId()) + detail + "</table></body></html>";
    	
    	createReportHTML();
    	if(fw.existsFileOrDir(tempPath)){
			fw.appendFile(tempPath + i_logRightFilename, text);
	    }
    	createLeftFrame(step.getId(), step.getStatus());
	}
}